﻿using Essensoft.Paylink.Alipay;
using Microsoft.AspNetCore.Mvc;
using Pay.DTO;
using V2 = Essensoft.Paylink.WeChatPay.V2;
using V3 = Essensoft.Paylink.WeChatPay.V3;

namespace Pay.Services.Imp
{
	/// <summary>
	/// 支付服务
	/// </summary>
	partial class PayService : IPayService
	{
		private readonly PayConfigDto _payConfig;
		private readonly IAlipayClient _alipayClient;
        private readonly IAlipayNotifyClient _notifyAlipayClient;
        private readonly V2.IWeChatPayClient _weChatPayV2Client;
		private readonly V3.IWeChatPayClient _weChatPayV3Client;

        /// <summary>
        /// ctor
        /// </summary>
        public PayService(
            PayConfigDto payConfig,
            IAlipayClient alipayClient,
            V2.IWeChatPayClient weChatPayV2Client,
            V3.IWeChatPayClient weChatPayV3Client,
            IAlipayNotifyClient notifyAlipayClient)
        {
            _payConfig = payConfig;
            _alipayClient = alipayClient;
            _weChatPayV2Client = weChatPayV2Client;
            _weChatPayV3Client = weChatPayV3Client;
            _notifyAlipayClient = notifyAlipayClient;
        }

        /// <summary>
        /// 支付
        /// </summary>
        public async Task<LayuiResultDto<PayResponseDto>> CommonPayAsync(PayRequestDto model)
		{
			var payResult = new PayResponseDto
			{
				AppId = _payConfig.AppId,
				OutTradeNo = model.OutTradeNo,
				PayCategory = model.PayCategory,
				PaySource = model.PaySource
			};
			var result = new LayuiResultDto<PayResponseDto> { Data = payResult };
			switch (model.PayCategory)
			{
				case PayCategoryEnum.AliPay:
					await AliPayAsync(model, result);
					break;
				case PayCategoryEnum.WechatPay:
					await WechatPayAsync(model, result);
					break;
				default:
					result.Code = 10000;
					result.Msg = "支付类型不支持，开发中";
					break;
			}

			return result;
		}

        /// <summary>
        /// 退款
        /// </summary>
        public async Task<LayuiResultDto<RefundResponseDto>> CommonRefundAsync(RefundRequestDto model)
		{
			var redundResult = new RefundResponseDto
			{
				AppId = _payConfig.AppId,
				OutTradeNo = model.OutTradeNo,
				RefundNo = model.RefundNo,
				PayCategory = model.PayCategory
			};
			var result = new LayuiResultDto<RefundResponseDto> { Data = redundResult };
            var isV3 = _payConfig.WechatPayVersion?.ToUpperInvariant() == "V3";
            switch (model.PayCategory)
            {
                case PayCategoryEnum.AliPay:
                    await AliRefundAsync(model, result);
                    break;
                case PayCategoryEnum.WechatPay:
                    await (isV3 ? WechatPayV3RefundAsync(model, result) : WechatPayV2RefundAsync(model, result));
                    break;
                default:
                    result.Code = 10000;
                    result.Msg = "退款类型不支持，开发中";
                    break;
            }

            return result;
		}

		/// <summary>
		/// 支付宝支付/退款回调
		/// </summary>
		public async Task<IActionResult> AliNotifyAsync(PaySourceEnum paySource, HttpRequest request)
		{
			var pushData = new NotifyResultDto { PayCategory = PayCategoryEnum.AliPay };
			switch (paySource)
			{
				case PaySourceEnum.App:
                    await AliNotifyAppAsync(pushData, request);
                    break;
				case PaySourceEnum.PCWeb:
                    await AliNotifyPcWebAsync(pushData, request);
                    break;
				case PaySourceEnum.MobileWeb:
                    await AliNotifyMobileWebAsync(pushData, request);
                    break;
				case PaySourceEnum.QRCode:
					await AliNotifyQRCodeAsync(pushData, request);
                    break;
				default:
					pushData.Exception = "不支付的支付渠道方式";
					break;
			}

			return AlipayNotifyResult.Success;
        }

        #region IDisposable
        /// <summary>
        /// dispose
        /// </summary>
        public void Dispose()
		{
		}
		#endregion

		#region private methods
		/// <summary>
		/// 支付宝支付
		/// </summary>
		private async Task AliPayAsync(PayRequestDto model, LayuiResultDto<PayResponseDto> result)
		{
			switch (model.PaySource)
			{
				case PaySourceEnum.App:
					await AliPayAppAsync(model, result);
					break;
				case PaySourceEnum.PCWeb:
					await AliPayPCWebAsync(model, result);
					break;
				case PaySourceEnum.MobileWeb:
					await AliPayMobileWebAsync(model, result);
					break;
				case PaySourceEnum.QRCode:
					await AliPayQRCodeAsync(model, result);
					break;
				case PaySourceEnum.PassiveCode:
					await AliPayPassiveQRCodeAsync(model, result);
					break;
				default:
					result.Code = 10000;
					result.Msg = "支付宝支付渠道不支持,开发中";
					break;
			}
		}

		/// <summary>
		/// 微信支付
		/// </summary>
		private async Task WechatPayAsync(PayRequestDto model, LayuiResultDto<PayResponseDto> result)
		{
			var isV3 = _payConfig.WechatPayVersion?.ToUpperInvariant() == "V3";
			switch (model.PaySource)
			{
				case PaySourceEnum.App:
					await (isV3 ? WechatPayV3AppAsync(model, result) : WechatPayV2AppAsync(model, result));
					break;
				case PaySourceEnum.Public:
					await (isV3 ? WechatPayV3MPAsync(model, result) : WechatPayV2MPAsync(model, result));
					break;
				case PaySourceEnum.MobileWeb:
					await (isV3 ? WechatPayV3MobileWebAsync(model, result) : WechatPayV2MobileWebAsync(model, result));
					break;
				case PaySourceEnum.QRCode:
					await (isV3 ? WechatPayV3QRCodeAsync(model, result) : WechatPayV2QRCodeAsync(model, result));
					break;
				case PaySourceEnum.PassiveCode:
					await WechatPayV2PassiveQRCodeAsync(model, result);
					break;
				case PaySourceEnum.Miniprogram:
					await (isV3 ? WechatPayV3MiniprogramAsync(model, result) : WechatPayV2MiniprogramAsync(model, result));
					break;
				default:
					result.Code = 10000;
					result.Msg = "微信支付渠道不支持,开发中";
					break;
			}
		}
		#endregion
	}
}